using System;
using System.Collections.Generic;
/// <summary>
/// 事件中心，用于管理游戏中的各类事件
/// 支持多参数传递和无参数事件
/// </summary>  
public class EventCenter
{
    //事件存储字典
    private static Dictionary<string, Delegate> eventDic = new();

    // 私有构造函数，确保单例
    private EventCenter() { }

    /// <summary>
    /// 注册无参数事件
    /// </summary>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void AddEventListener(string eventName, Action onEvent)
    {
        AddListener(eventName, onEvent);
    }

    /// <summary>
    /// 注册带一个参数的事件
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void AddEventListener<T>(string eventName, Action<T> onEvent)
    {
        AddListener(eventName, onEvent);
    }

    /// <summary>
    /// 注册带两个参数的事件
    /// </summary>
    /// <typeparam name="T1">第一个参数类型</typeparam>
    /// <typeparam name="T2">第二个参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void AddEventListener<T1, T2>(string eventName, Action<T1, T2> onEvent)
    {
        AddListener(eventName, onEvent);
    }
    
    /// <summary>
    /// 注册带三个参数的事件
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    /// <typeparam name="T3"></typeparam>
    /// <param name="eventName"></param>
    /// <param name="onEvent"></param>
    public static void AddEventListener<T1, T2, T3>(string eventName, Action<T1, T2, T3> onEvent)
    {
        AddListener(eventName, onEvent);
    }
    /// <summary>
    /// 注销无参数事件
    /// </summary>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void RemoveEventListener(string eventName, Action onEvent)
    {
        RemoveListener(eventName, onEvent);
    }

    /// <summary>
    /// 注销带一个参数的事件
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void RemoveEventListener<T>(string eventName, Action<T> onEvent)
    {
        RemoveListener(eventName, onEvent);
    }

    /// <summary>
    /// 注销带两个参数的事件
    /// </summary>
    /// <typeparam name="T1">第一个参数类型</typeparam>
    /// <typeparam name="T2">第二个参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="onEvent">事件回调</param>
    public static void RemoveEventListener<T1, T2>(string eventName, Action<T1, T2> onEvent)
    {
        RemoveListener(eventName, onEvent);
    }

    /// <summary>
    /// 注销带三个参数的事件
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    /// <typeparam name="T3"></typeparam>
    /// <param name="eventName"></param>
    /// <param name="onEvent"></param>
    public static void RemoveEventListener<T1, T2 ,T3>(string eventName, Action<T1, T2, T3> onEvent)
    {
        RemoveListener(eventName, onEvent);
    }
    /// <summary>
    /// 触发无参数事件
    /// </summary>
    /// <param name="eventName">事件名称</param>
    public static void TriggerEvent(string eventName)
    {
        if (eventDic.TryGetValue(eventName, out Delegate del))
        {
            if (del is Action action)
                action.Invoke();
            else
                throw new ArgumentException($"事件 {eventName} 类型不匹配，事件必须为无参数的委托");
        }
    }

    /// <summary>
    /// 触发带一个参数的事件
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="param">事件参数</param>
    public static void TriggerEvent<T>(string eventName, T param)
    {
        if (eventDic.TryGetValue(eventName, out Delegate del))
        {
            if (del is Action<T> action)
                action.Invoke(param);
            else
                throw new ArgumentException($"事件 {eventName} 类型不匹配，事件必须为带一个参数的委托");
        }
    }

    /// <summary>
    /// 触发带两个参数的事件
    /// </summary>
    /// <typeparam name="T1">第一个参数类型</typeparam>
    /// <typeparam name="T2">第二个参数类型</typeparam>
    /// <param name="eventName">事件名称</param>
    /// <param name="param1">第一个参数</param>
    /// <param name="param2">第二个参数</param>
    public static void TriggerEvent<T1, T2>(string eventName, T1 param1, T2 param2)
    {
        if (eventDic.TryGetValue(eventName, out Delegate del))
        {
            if (del is Action<T1, T2> action)
                action.Invoke(param1, param2);
            else
                throw new ArgumentException($"事件 {eventName} 类型不匹配,事件必须为带两个参数的委托");
        }
    }
    public static void TriggerEvent<T1, T2 ,T3>(string eventName, T1 param1, T2 param2, T3 param3)
    {
        if (eventDic.TryGetValue(eventName, out Delegate del))
        {
            if (del is Action<T1, T2, T3> action)
                action.Invoke(param1, param2, param3);
            else
                throw new ArgumentException($"事件 {eventName} 类型不匹配,事件必须为带两个参数的委托");
        }
    }
    /// <summary>
    /// 内部添加事件监听的实现
    /// </summary>
    private static void AddListener(string eventName, Delegate callback)
    {
        if (!eventDic.ContainsKey(eventName))
            eventDic[eventName] = null;

        // 检查委托类型是否一致
        Delegate existingDelegate = eventDic[eventName];
        if (existingDelegate != null && existingDelegate.GetType() != callback.GetType())
            throw new ArgumentException($"事件 {eventName} 已存在不同类型的委托");

        eventDic[eventName] = Delegate.Combine(eventDic[eventName], callback);
    }

    /// <summary>
    /// 内部移除事件监听的实现
    /// </summary>
    private static void RemoveListener(string eventName, Delegate callback)
    {
        if (eventDic.TryGetValue(eventName, out Delegate existingDelegate))
        {
            // 检查委托类型是否一致
            if (existingDelegate.GetType() != callback.GetType())
                throw new ArgumentException($"事件 {eventName} 委托类型不匹配");

            Delegate newDelegate = Delegate.Remove(existingDelegate, callback);

            if (newDelegate == null)
                eventDic.Remove(eventName);
            else
                eventDic[eventName] = newDelegate;
        }
    }

    /// <summary>
    /// 清除所有事件
    /// </summary>
    public void Clear() => eventDic.Clear();

}
